const express = require('express')
const cors = require('cors');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const bodyParser = require('body-parser');
const { NodeVM, VM, VMScript } = require('vm2');
const mathjs = require('mathjs');
const fs = require('fs');
const path = require('path');


const matrixCode = `

function addMatrices(matrixA, matrixB, fn) {
  // 获取两个矩阵的尺寸
  const sizeA = mathjs.size(matrixA);
  const sizeB = mathjs.size(matrixB);

  // 检查行数和列数是否一致
  if (!(sizeA[0] !== sizeB[0] || sizeA[1] !== sizeB[1])) {
    fn()

  }

}

// 封装矩阵相减的方法
function subtractMatrices(matrixA, matrixB, fn) {
  // 获取两个矩阵的尺寸
  const sizeA = mathjs.size(matrixA);
  const sizeB = mathjs.size(matrixB);

  // 检查行数和列数是否一致
  if ((sizeA[0] !== sizeB[0] || sizeA[1] !== sizeB[1])) {
    fn()
  }
}

`

const corsOptions = {
    origin: '*', // 允许所有来源
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization'],
};
const app = express();
// 解析 application/json 类型的数据
app.use(cors(corsOptions));
// 中间件解析 JSON 请求体
// app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// app.use(express.urlencoded({ extended: true }));
const port = 3000;
// function generateRandomArray(length, min, max) {
//     const array = [];
//     for (let i = 0; i < length; i++) {
//         const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
//         array.push(randomNumber);
//     }
//     return array;
// }

app.get('/', (req, res) => {
    res.send('Hello World!');
})
// app.get('/getData', (req, res) => {
//     res.send(generateRandomArray(20, 0, 100))
// })
// app.post('/send', (req, res) => {
//     console.log(req.body.name);
//     const filePath = path.join(__dirname, 'data.sb3'); // 保存路径
//     console.log('filePath');
//     fs.writeFile(filePath, JSON.stringify(req.body.name, null, 2), (err) => {
//         if (err) {
//             console.error('Error writing file:', err);
//             return res.status(500).send('Error saving data');
//         }

//         console.log('Data saved to', filePath);
//         res.status(200).send('Data saved successfully');
//     });

// })

app.post('/api/get', (req, res) => {
    const script = req.body.script;
    const variables = extractGlobalVariables(script);//从代码中提取的变量列表
    res.status(200).json({ paramNames: variables, success: true, message: '运行成功' });
});

app.post('/api/run2', (req, res) => {
    const data = req.body;
    console.log('接收到的参数:', JSON.stringify(data.script));
    console.log('接收到的参数:', JSON.stringify(data.paramNames));
    console.log('接收到的参数:', JSON.stringify(data.resultParamName));
    return res.status(200).json({
        success: true,
        message: '运行成功',
        data: {}
    });
})
//运行代码
app.post('/api/run', (req, res) => {

    let ext = {};//保存处理后的变量
    //console.log(req.body);
    // let script = req.body.script;
    let script = removeLinesStartingWith(req.body.script, "Mconst");
    const outVar = req.body.resultParamName;//接口接收的变量列表
    const varList = req.body.paramNames;//接口接收的变量列表
    // console.log('接收到的参数:',req.body.resultParamName)
    // return res.status(200).join({});
    const variables = extractGlobalVariables(script);//从代码中提取的变量列表
    // const scriptRead = 'var ' + variables.map(item => `${item}=${varList[item] ? varList[item] : 0};`).join('');//开始运行之前赋值
    // const scriptRead = 'var ' + variables.map(item => `${item}=${varList[item] ? varList[item] : 0};`).join('');//开始运行之前赋值
    const str = [];

    for (const key in varList) {
        if (varList.hasOwnProperty(key)) { // 确保是对象自身的属性
            // const value = convertToNumber(varList[key]);
            // if (typeof varList[key] === 'string') {
            //     varList[key] = convertSingleQuotesToDouble(varList[key]);
            // } 
            let value = parseStringToType(varList[key])
            // console.log(JSON.stringify(a));
            // let value = key + " = " + parseStringToType(varList[key]) + ";";
            // console.log("变:", value)
            if (typeof value === 'object') {
                value = JSON.stringify(value)
            }
            str.push(`${key}=${value};\r\n`);
            // str.push(" " + key + " = " + value + ";\r\n");

        }
    }

    console.log('定义了变量:', req.body.paramNames);



    const scriptRead = '\r\n var ' + str.join('') + '\r\n';
    console.log('定义了变量:', scriptRead);
    const index = script.indexOf(';');
    if (script.startsWith('var')) {
        if (index !== -1) {
            script = "const mathjs = require('mathjs'); \r\n" + script.slice(0, index + 1) + scriptRead + script.slice(index + 1);
        }
    } else {

        script = "const mathjs = require('mathjs');\r\n" + scriptRead + script;
    }
    // script += matrixCode;//添加矩阵的方法
    // console.log('最后生成的代码:', script);

    // const merge = { ...varList, ...variables };
    //console.log('变量列表:', variables);
    //console.log('自定义的变量列表:', varList);

    const vm = new NodeVM({
        console: 'inherit',
        sandbox: { ext },
        require: {
            external: true,
            builtin: ['fs', 'path', 'set', 'math'],
            root: './',
        },
        timeout: 5000, // 设置超时为 5000 毫秒
    });

    const scriptOut = outVar.map(item => `ext.${item.variableName}=${item.value};`).join('');//拼装运行脚本后循环给变量赋值的代码
    // const scriptOut = variables.map(item => `ext.${item}=${item};`).join('');//拼装运行脚本后循环给变量赋值的代码
    // console.log('合并的变量列表:', scriptOut);
    // ${scriptRead}
    try {
        const wrappedCode = `
        ${script}
        ${matrixCode}
        ${scriptOut}
        `;
        vm.run(wrappedCode, 'vm.js');
        // console.log('运行结果:', ext);
        res.status(200).json({ result: ext, success: true, message: '运行成功' });
    } catch (err) {
        res.json({ result: null, success: false, message: err.message });
    }


});


app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
});


// 将字符串中的单引号字符串替换为双引号字符串
function convertSingleQuotesToDouble(jsCode) {
    // 使用正则表达式替换单引号包裹的字符串为双引号
    return jsCode.replace(/'([^']+)'/g, '"$1"');
}
// 删除指定开头的行
function removeLinesStartingWith(jsCode, prefix) {
    // 将代码按行分割
    const lines = jsCode.split('\n');

    // 使用 filter 保留不以指定前缀开头的行
    const filteredLines = lines.filter(line => !line.trim().startsWith(prefix));

    // 将过滤后的行重新合并成一个字符串
    return filteredLines.join('\n');
}
function parseStringToType(str) {
    // 尝试解析为 JSON
    try {
        const parsed = JSON.parse(str);
        // 如果解析结果是数组或对象，直接返回
        if (Array.isArray(parsed) || typeof parsed === 'object') {
            return parsed;
        }
    } catch (e) {
        // 解析失败，继续尝试其他类型
    }

    // 尝试解析为数字
    if (!isNaN(str)) {
        return parseFloat(str); // 转为数字
    }

    // 默认返回字符串
    return `"${str}"`;
}
// function convertToNumber(value, defaultValue = 0) {
//     const num = Number(value);
//     return isNaN(num) ? defaultValue : num;
// }
function convertToNumber(value) {
    const num = parseFloat(value);
    return isNaN(num) ? `'${value}'` : num;
}
/**
 * 提取脚本中的全局变量
 * @param {脚本} code 
 * @returns 
 */
function extractGlobalVariables(code) {
    //将代码转换为抽象语法树
    const ast = parser.parse(code, { sourceType: 'module' });

    const globalVariables = new Set();

    // 遍历AST收集全局变量
    traverse(ast, {
        //处理变量声明（var、let、const）
        VariableDeclarator(path) {
            // 检查变量是否在顶层声明
            if (path.parentPath.isVariableDeclaration() && path.parentPath.node.declarations.length > 0) {
                if (path.parentPath.parentPath.isProgram()) {
                    globalVariables.add(path.node.id.name);
                }
            }
        },
        // 处理函数声明和函数表达式
        FunctionDeclaration(path) {
            if (path.parentPath.isProgram()) {
                globalVariables.add(path.node.id.name);
            }
        },
        // 句柄函数表达式和箭头函数
        FunctionExpression(path) {
            if (path.node.id && path.parentPath.isProgram()) {
                globalVariables.add(path.node.id.name);
            }
        },
        ArrowFunctionExpression(path) {
            if (path.node.id && path.parentPath.isProgram()) {
                globalVariables.add(path.node.id.name);
            }
        },
        //处理全局变量赋值
        AssignmentExpression(path) {
            if (path.node.left.type === 'Identifier') {
                if (path.parentPath.isExpressionStatement() && path.parentPath.parentPath.isProgram()) {
                    globalVariables.add(path.node.left.name);
                }
            }
        }
    });
    return Array.from(globalVariables);
}